package registration;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;

import encryption.Hash;
import encryption.RSA;


import network.CAClient;
import network.Client;
import network.Operations;

public class ClientRegistration {
	private static final int SIZE_OF_RANDOM_PASSWORD = 10;
	public ClientRegistration(){
		
	}
	
	/**
	 * Takes Email and sends it to the server to add it in the database
	 * @param username
	 * @return true if succeeded and there is no user registered with that email
	 */
	public boolean register(String email){
		CAClient ca = new CAClient();
		String key = null;
		try {
			key= ca.CAClientFlow();
		} catch (NoSuchAlgorithmException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return false ;
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return false;
		}
		String keyMod = key.split(" ")[0];
		String keyExp = key.split(" ")[1];
		
		Client.client.sendMessage(Operations.REGISTER + " " );
		Client.client.receiveMessage();
		byte[] encryptedMessage = new RSA().rsaEncryptToBytes(email,keyMod , keyExp);
		Client.client.sendRSAMessage(encryptedMessage);
		
		
		String result = Client.client.receiveMessage();
		if(result.equals("" + Operations.REGISTRATION_COMPLETE)){
			return true;
		}
		else{
			return false;
		}
		
	}
	
	
	private String generateRandomPassword(){
		SecureRandom randomGenerator = new SecureRandom();
		
		String password = "";
		for(int i =0 ; i < SIZE_OF_RANDOM_PASSWORD ; i ++){
			int x = randomGenerator.nextInt(26);
			password += (char)(x+'A');
		}
		return password;
	}
	
	/**
	 * Takes email and password and sends them to the server
	 * They still need encryption
	 * @param hashedEmail
	 * @param password
	 * @return true if succeeded
	 */
	public boolean activate(String hashedEmail , String password) {

		String randomPassword = generateRandomPassword();
		CAClient ca = new CAClient();
		String key = null;
		try {
			key= ca.CAClientFlow();
		} catch (NoSuchAlgorithmException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return false ;
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return false;
		}
		String keyMod = key.split(" ")[0];
		String keyExp = key.split(" ")[1];
		String message =  hashedEmail + " " + randomPassword;
		RSA rsa = new RSA();
		byte[] messageInBytes = rsa.rsaEncryptToBytes(message, keyMod, keyExp);
		
		Client.client.sendMessage(Operations.ACTIVATE + "" );
		Client.client.receiveMessage();
		Client.client.sendRSAMessage(messageInBytes);
		
		String result = Client.client.receiveMessage();
		if(result.startsWith("" + Operations.ACTIVATE_FAILED)){
			return false;
		}
		
		String  saltString = result.substring(2);
		byte[] salt = null;
		try {
			salt = Hash.base64ToByte(saltString);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		String hashedPassword = "";
		try {
			hashedPassword = Hash.getHashSalt(password, salt, "SHA-1");
			System.out.println(Hash.byteToBase64(salt) + "     salt in reg  " +hashedPassword);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		String message2 = hashedPassword + " " + randomPassword ;
		byte[] message2InBytes = rsa.rsaEncryptToBytes(message2, keyMod, keyExp);
		return Client.client.sendRSAMessage(message2InBytes);
	}
	/**
	 * Checks if the email is in the correct format
	 * We need to modify it to be guc student email
	 * @param email
	 * @return true if the email is in correct format
	 */
	public static boolean checkEmailFormat(String email)
	{
		return email.matches("[a-zA-Z0-9.]+[.][a-zA-Z0-9.]+@student.guc.edu.eg");
	}
	
	/**
	 * Checks if the password is strong enough
	 * @param password
	 * @return true if the password is strong
	 */
	public static boolean checkPasswordStrength(String password)
	{
		if(password.length() < 8) return false;
		
		return password.matches("[a-zA-Z]*[0-9]+[a-zA-Z]*");
	}
	
	/**
	 * Input username and send it to the server.
	 * This method will be removed and the GUI will be the one responsible 
	 * to initialize this class  
	 */
	public static void RegisterUsername(){
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		System.out.println("Write your mail");
		String email = "";
		try {
			email = br.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(!checkEmailFormat(email))
		{
			System.out.println("Invalid Email");
			return;
		}
		ClientRegistration activate = new ClientRegistration();
		boolean activated = activate.register(email);
		if(activated){
			System.out.println("Please check your email");
		}
		else
		{
			System.out.println("User already exists");
		}
	}

	/** 
	 * Input Activation Code and sending to the server
	 * This method will be removed and the GUI will be the one responsible 
	 * to initialize this class  
	 */
	public static void ActivateUsername(){
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		System.out.println("Write your Activation Code:");
		String hashedEmail = "";
		String password = "";
		try {
			hashedEmail = br.readLine();
			System.out.println("Write your password");
			password = br.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		ClientRegistration activate = new ClientRegistration();
		boolean activated = activate.activate(hashedEmail , password);
		if(activated){
			System.out.println("activated");
		}
		else
		{
			System.out.println("Wrong Activation Code");
		}
	}
	
}
